use crate::seventh::se_7_37::ast::{Expr, Name, Stmt};
use crate::seventh::se_7_37::visit::Visitor;

/// 访问者模式
/// Rust 中另一个重要的模式是访问者模式 (Visitor Pattern)。访问者模式用于将数据结构
// 和作用于结构上的操作解耦。 Rust 语言自身在解析抽象语法树时就用到了访问者模式。
pub fn start() {}

/// 这段代码是用于构建抽象语法树的 ， Rust语法中包含语句、 标识符名称和表达式，
/// 分别被定义于 ast模块中 的 Stmt、 Name 和 Expr来表示。
/// 这些包含在 ast 模块中的类型虽然各不相同，但是它们整体是在描述同一个抽象语法树结构的。
/// 因此，整个抽象语法树就是一个异构的结构，其中的每个语法节点都是不同的类型，
/// 对于这些节点的操作也各不相同。语法节点是基本确定好的，变化不会太大，但是对节点的操作需要经常改动，
/// 比如 Rust现在正处于发展期，会定时添加一些新特性。使用访问者模式 将不变的节点和变化的操作分离开，
/// 可以方便后续扩展。所以， 访问者模式一般包含两个层次.
/// · 定义需要操作的元素。
/// · 定义相关的操作。
mod ast {
    pub enum Stmt {
        Expr(Expr),

        Let(Name, Expr),
    }

    pub struct Name {
        value: String,
    }

    pub enum Expr {
        IntLit(i64),
        Add(Box<Expr>, Box<Expr>),
        Sub(Box<Expr>, Box<Expr>),
    }
}

/// visit模块中的 Visitor trait则定义了相关的操作。 所以在解析语法树的时候，只需要为解析器
/// 实现相关的 visit方法即可操作相关节点
mod visit {
    use super::ast::*;

    pub trait Visitor<T> {
        fn visit_name(&mut self, n: &Name) -> T;
        fn visit_stmt(&mut self, s: &Stmt) -> T;
        fn visit_expr(&mut self, s: &Expr) -> T;
    }
}

struct Interpreter;

impl Visitor<i64> for Interpreter {
    fn visit_name(&mut self, n: &Name) -> i64 {
        panic!()
    }

    fn visit_stmt(&mut self, s: &Stmt) -> i64 {
        match s {
            Stmt::Expr(e) => self.visit_expr(e),
            Stmt::Let(..) => unimplemented!(),
        }
    }

    fn visit_expr(&mut self, s: &Expr) -> i64 {
        match s {
            Expr::IntLit(n) => *n,
            Expr::Add(lhs, rhs) => self.visit_expr(lhs) + self.visit_expr(rhs),
            Expr::Sub(lhs, rhs) => self.visit_expr(lhs) - self.visit_expr(rhs),
        }
    }
}

// Serde库中的访问者模式
// 它是一个对 Rust 数据结构进行序列化和反序列化的高效框架。
